package com.onepiece.shipelves.common.myutils.linked;

import java.util.HashMap;

class Entry<K, V>{
    public Entry pre;
    public Entry next;

    public K key;
    public V value;

}

public class LRUCache<K, V> {

    private final int MAX_SIZE;
    private Entry first;
    private Entry last;

    private HashMap<K, Entry<K, V>> hashMap;

    public LRUCache(int max_sie) {
        MAX_SIZE = max_sie;
        hashMap = new HashMap<>();
    }

    public void put(K key, V value){
        Entry entry = getEntry(key);
        if(entry == null){
            if(hashMap.size() > MAX_SIZE){
                hashMap.remove(last.key);
                removeLast();
            }
            entry = new Entry();
            entry.key = key;
        }
        entry.value = value;
        moveToFirst(entry);
        hashMap.put(key, entry);

    }

    private void moveToFirst(Entry entry) {
        if(first == entry) return;
        if(entry.pre != null) entry.pre.next = entry.next;
        if(entry.next != null) entry.next.pre = entry.pre;
        if(entry == last) last = last.pre;
        entry.next = first;
        first.pre = entry;
        first = entry;
        entry.pre = null;
    }

    private void removeLast() {
        if(last != null){
            last = last.pre;
            if(last == null) first = null;
            else last.next = null;
        }
    }

    private Entry<K, V> getEntry(K key) {
        return hashMap.get(key);
    }

    public V get(K key){
        Entry<K, V> entry = getEntry(key);
        if(entry == null) return null;
        moveToFirst(entry);
        return entry.value;
    }

    public void remove(K key){
        Entry entry = getEntry(key);
        if(entry != null){
            if(entry.pre != null) entry.pre.next = entry.next;
            if(entry.next != null) entry.next.pre = entry.pre;
            if(entry == first) first = entry.next;
            if(entry == last) last = entry.pre;
        }
        hashMap.remove(key);
    }



    //
}
